//
// Created by denglibin on 19-4-14.
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/*
进程间通信-fifo
FIFO又名有名管道，相对于上述管道而言。管道没有名字，因此只能在具有共同祖先进程的各个进程之间通信，
无法在无亲缘关系的两个进程之间创建一个管道进行通信。为此有了FIFO，类似管道，也是一个单向（半双工）数据流，
每个FIFO有一个路径名与之关联，从而允许无亲缘关系的进程访问同一个FIFO。FIFO有mkfifo函数创建。
int mkfifo(const char *pathname,mode_t mode); 成功返回0，出错返回-1。pathname是一个普通的路径名，是FIFO的名字，mode指定文件的权位
在创建FIFO后，必须打开来读或者打开来写，不能打开来既读既写（因为FIFO是半双工）
*/
#define FIFO1   "/tmp/fifo.1"
static int main_(int argc, char* argv[])
{
    int readFd, writeFd;//文件描述符
    pid_t childPid;//子进程id
    char buf[1024];
    memset(buf,0,sizeof(buf));
    //创建FIFO
    if(mkfifo(FIFO1, FILE_MODE)<0 &&(errno != EEXIST))
    {
        perror("mkfifo() error");
        exit(-1);
    }
    //创建子进程
    childPid = fork();
    if(childPid == -1)
    {
        perror("fork() error");
        exit(-1);
    }
    if(childPid == 0)//子进程
    {
        //第一个参数为路径名
        /*第二个参数为文件状态标志：
        O_RDONLY或0：可读
        O_WRONLY或1：可写
        O_RDWR或2：可执行
        O_APPEND：每次写时都加到文件的尾部
        O_CREAT：若此文件不存在则创建它，使用此选项时，需同时说明第三个参数mode，用其说明该新文件的存取许可权位
        O_EXCL：如果同时指定了O_CREAT,而文件已经存在，则出错，这可测试一个文件是否存在，如果不存在则创建此文件成为一个原子操作
        O_TRUNC：如果此文件存在，而且为只读或只写成功打开，则将其长度截短为0
        O_NOCTTY：如果pathname指的是终端设备，则不将此设备分配作为此进程的控制终端
        O_NONBLOCK：如果pathname指的是一个FIFO，一个块特殊文件或一个字符特殊文件，则此选择项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式
        O_SYNC：使每次write都等到物理I/O操作完成
        */
        readFd = open(FIFO1,O_RDONLY,0); //读的方式打开（当前没有任何进程打开某个FIFO来写的时候，打开该FIFO来读的进程将会阻塞）
        read(readFd,buf,sizeof(buf)); //读取数据到缓冲区
        printf("read data is: %s\n",buf);
        exit(0);
    }
        //父进程
    else
    {
        sleep(1);
        writeFd = open(FIFO1,O_WRONLY,0);//写的方式打开
        char writeBuf[1024] = "hello fifo";
        write(writeFd,writeBuf,strlen(writeBuf)); //写数据
        close(writeFd);
    }
    return 0;
}
